/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package abstractClasses;

import facades.AbstractFacade;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.enterprise.event.TransactionPhase;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import qualifiers.ChosenEntityEvent;
import qualifiers.CreatedEntityEvent;
import qualifiers.EditedEntityEvent;
import qualifiers.PreRemoveEntityEvent;
import qualifiers.RemovedEntityEvent;

/**
 *
 * @author Alvaro
 * @param <T>
 * @param <F>
 */
public abstract class AbstractEntityList<T,F extends AbstractFacade> {
    
    @Inject
    private Instance<F> entityFacadeInstance;
    
    private F entityFacade;
    
    private List<T> entityList;
    
    @Inject
    @ChosenEntityEvent
    private Event<T> chosenEntityEvent;
    
    @Inject
    @CreatedEntityEvent
    private Event<T> createdEntityEvent;
    
    @Inject
    @PreRemoveEntityEvent
    private Event<T> preRemoveEntityEvent;
    
    @Inject
    @RemovedEntityEvent
    private Event<T> removedEntityEvent;

    private T chosenEntity;
    
    @PostConstruct
    public void init(){
        initEntityFacade();
        initEntityList();
    }
    
    public void initEntityFacade(){
        setEntityFacade(getEntityFacadeInstance().get());
        
    }
    
    public void initEntityList(){
        entityList=getEntityFacade().findAll();
    }
    
    public void chooseEntity(T e){
        chosenEntity=e;
        getChosenEntityEvent().fire(chosenEntity);
    }
    
    public String redirectToViewEntity(){
        return null;
    }
    
    public void onEditedEntity(@Observes(during=TransactionPhase.AFTER_SUCCESS,notifyObserver = Reception.IF_EXISTS) @EditedEntityEvent T e){
        if(getEntityList()==null){
            setEntityList(new ArrayList<T>());
            getEntityList().add(e);
        }
        else if(getEntityList().contains(e)){
            Collections.replaceAll(getEntityList(), e, e);
        }
        else{
            onCreatedEntity(e);
        }
    }
    
    public void onCreatedEntity(@Observes(during=TransactionPhase.AFTER_SUCCESS,notifyObserver = Reception.IF_EXISTS) @CreatedEntityEvent T e){
       if(getEntityList()==null){
           setEntityList(new ArrayList<T>());
       }
       if(!getEntityList().contains(e)){
           getEntityList().add(e);
       }
    }
    
    public void onRemovedEntity(@Observes(during=TransactionPhase.AFTER_SUCCESS,notifyObserver = Reception.IF_EXISTS) @RemovedEntityEvent T e){
        getEntityList().remove(e);
    }
    
    public void deleteEntity(T e){
        getPreRemoveEntityEvent().fire(e);
        getEntityFacade().remove(e);
        getRemovedEntityEvent().fire(e);
    }
    
    public void deleteChosenEntity(){
        if(getChosenEntity()!=null){
            getPreRemoveEntityEvent().fire(getChosenEntity());
            getEntityFacade().remove(getChosenEntity());
            getRemovedEntityEvent().fire(getChosenEntity());
        }
        
    }
    /**
     * @return the entityList
     */
    public List<T> getEntityList() {
        return entityList;
    }

    /**
     * @param entityList the entityList to set
     */
    public void setEntityList(List<T> entityList) {
        this.entityList = entityList;
    }

    /**
     * @return the chosenEntity
     */
    public T getChosenEntity() {
        return chosenEntity;
    }

    /**
     * @param chosenEntity the chosenEntity to set
     */
    public void setChosenEntity(T chosenEntity) {
        this.chosenEntity = chosenEntity;
    }

    /**
     * @return the chosenEntityEvent
     */
    public Event<T> getChosenEntityEvent() {
        return chosenEntityEvent;
    }

    /**
     * @param chosenEntityEvent the chosenEntityEvent to set
     */
    public void setChosenEntityEvent(Event<T> chosenEntityEvent) {
        this.chosenEntityEvent = chosenEntityEvent;
    }

    /**
     * @return the preRemoveEntityEvent
     */
    public Event<T> getPreRemoveEntityEvent() {
        return preRemoveEntityEvent;
    }

    /**
     * @param preRemoveEntityEvent the preRemoveEntityEvent to set
     */
    public void setPreRemoveEntityEvent(Event<T> preRemoveEntityEvent) {
        this.preRemoveEntityEvent = preRemoveEntityEvent;
    }

    /**
     * @return the removedEntityEvent
     */
    public Event<T> getRemovedEntityEvent() {
        return removedEntityEvent;
    }

    /**
     * @param removedEntityEvent the removedEntityEvent to set
     */
    public void setRemovedEntityEvent(Event<T> removedEntityEvent) {
        this.removedEntityEvent = removedEntityEvent;
    }

    /**
     * @return the entityFacade
     */
    public F getEntityFacade() {
        return entityFacade;
    }

    /**
     * @param entityFacade the entityFacade to set
     */
    public void setEntityFacade(F entityFacade) {
        this.entityFacade = entityFacade;
    }

    /**
     * @return the createdEntityEvent
     */
    public Event<T> getCreatedEntityEvent() {
        return createdEntityEvent;
    }

    /**
     * @param createdEntityEvent the createdEntityEvent to set
     */
    public void setCreatedEntityEvent(Event<T> createdEntityEvent) {
        this.createdEntityEvent = createdEntityEvent;
    }

    /**
     * @return the entityFacadeInstance
     */
    public Instance<F> getEntityFacadeInstance() {
        return entityFacadeInstance;
    }

    /**
     * @param entityFacadeInstance the entityFacadeInstance to set
     */
    public void setEntityFacadeInstance(Instance<F> entityFacadeInstance) {
        this.entityFacadeInstance = entityFacadeInstance;
    }
    
    
}
